﻿using ReportSystem_XY.Utility;
using System;
using System.Collections.Generic;
using System.Data.OleDb;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static ReportSystem_XY.WinCCArchive.Common;
using ReportSystem_XY.Common;
using System.Xml.XPath;
using System.Threading;

namespace ReportSystem_XY.WinCCArchive
{


    public class ArchiveHelper
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name="index">Tag索引</param>
        /// <param name="colName">表格列名称</param>
        /// <param name="tfrom">开始时间Local</param>
        /// <param name="tto">结束时间Local</param>
        /// <param name="sampletime">采样时间</param>
        /// <returns></returns>
        public static DataTable GetArchiveData(int index, string colName, string tfrom, string tto, string timeSpace = "3600", DtySimple simple = DtySimple.First)
        {
            string sql = "TAG:R,('" + index.ToString() + "'),'" + GetWinCCDateTime(tfrom) + "','" + GetWinCCDateTime(tto) + "'," + $"'TIMESTEP={timeSpace},{(int)simple}'";
            return GetArchiveTableOne(sql, colName);
        }

        public static DataTable GetArchiveData(string ArchiveTagName, string colName, string tfrom, string tto, string timeSpace = "3600", DtySimple simple = DtySimple.First)
        {
            string sql = "TAG:R,('" + ArchiveTagName + "'),'" + GetWinCCDateTime(tfrom) + "','" + GetWinCCDateTime(tto) + "'," + $"'TIMESTEP={timeSpace},{(int)simple}'";
            return GetArchiveTableOne(sql, colName);
        }

        public static List<DataTable> GetArchiveDataList(List<int> index, List<string> colNames, string tfrom, string tto, string timeSpace = "3600", DtySimple simple = DtySimple.First)
        {
            if (index.Count != colNames.Count)
            {
                Logs.Info("Tag数量和名称不一致");
                return null;
            }
            List<DataTable> list = new List<DataTable>();
            for (int i = 0; i < index.Count; i++)
            {
                string sql = "TAG:R," + index[i].ToString() + ",'" + GetWinCCDateTime(tfrom) + "','" + GetWinCCDateTime(tto) + "'," + $"'TIMESTEP={timeSpace},{(int)simple}'";
                list.Add(GetArchiveTableOne(sql, colNames[i]));
            }
            return list;
        }
        /// <summary>
        /// 根据标签名称查询
        /// </summary>
        /// <param name="ArchiveTagNameList"></param>
        /// <param name="colNames"></param>
        /// <param name="tfrom"></param>
        /// <param name="tto"></param>
        /// <param name="timeSpace"></param>
        /// <param name="simple"></param>
        /// <returns></returns>
        public static List<DataTable> GetArchiveDataList(List<string> ArchiveTagNameList, string tfrom, string tto, string timeSpace = "3600", DtySimple simple = DtySimple.First)
        {
            if (ArchiveTagNameList.Count == 0)
            {
                Logs.Info("Tag数量为0");
                return null;
            }
            List<DataTable> list = new List<DataTable>();
            for (int i = 0; i < ArchiveTagNameList.Count; i++)
            {
                string sql = "TAG:R,('" + ArchiveTagNameList[i] + "'),'" + GetWinCCDateTime(tfrom) + "','" + GetWinCCDateTime(tto) + "'," + $"'TIMESTEP={timeSpace},{(int)simple}'";
                list.Add(GetArchiveTableOne(sql, ArchiveTagNameList[i]));
            }
            return list;
        }

        private static DataTable GetArchiveTableOne(string sql, string colName)
        {
            DataTable dt = OleDbHelper.ExecuteDataTable(sql);
            dt.Columns["RealValue"].ColumnName = colName;
            dt.Columns["Timestamp"].ColumnName = "logtime";
            return dt.DefaultView.ToTable(false, new string[] { "logtime", colName });
        }

        public static DataTable MergeDataTable(List<int> index, List<string> colNames, string tfrom, string tto, string timeSpace = "3600", DtySimple simple = DtySimple.First)
        {
            if (index.Count != colNames.Count)
            {
                Logs.Info("Tag数量和名称不一致");
                return null;
            }
            List<DataTable> list = new List<DataTable>();
            for (int i = 0; i < index.Count; i++)
            {
                string sql = "TAG:R," + index[i].ToString() + ",'" + GetWinCCDateTime(tfrom) + "','" + GetWinCCDateTime(tto) + "'," + $"'TIMESTEP={timeSpace},{(int)simple}'";
                list.Add(GetArchiveTableOne(sql, colNames[i]));
            }
            return MergeDataTable(list);
        }

        public static DataTable MergeDataTable(string strIndex, string strColNames, string tfrom, string tto, string timeSpace = "3600", DtySimple simple = DtySimple.First)
        {
            List<string> index = strIndex.GetStrList(',', false);
            List<string> colNames = strColNames.GetStrList(',', false);
            if (index.Count != colNames.Count)
            {
                Logs.Info("Tag数量和名称不一致");
                return null;
            }
            List<DataTable> list = new List<DataTable>();
            for (int i = 0; i < index.Count; i++)
            {
                string sql = "TAG:R," + index[i] + ",'" + GetWinCCDateTime(tfrom) + "','" + GetWinCCDateTime(tto) + "'," + $"'TIMESTEP={timeSpace},{(int)simple}'";
                list.Add(GetArchiveTableOne(sql, colNames[i]));
            }
            return MergeDataTable(list);
        }

        public static DataTable MergeCTDataTable(string strIndex, string strColNames, string tfrom, string tto, out bool result,string timeSpace = "3600", DtySimple simple = DtySimple.First)
        {   
            List<string> index = strIndex.GetStrList(',', false);
            List<string> colNames = strColNames.GetStrList(',', false);
            if (index.Count != colNames.Count)
            {
                Logs.Info("Tag数量和名称不一致");
                result = false;
                return null;
            }
            List<DataTable> list = new List<DataTable>();
            for (int i = 0; i < index.Count; i++)
            {
                string sql = "TAG:R," + index[i] + ",'" + GetWinCCDateTime(tfrom) + "','" + GetWinCCDateTime(tto) + "'," + $"'TIMESTEP={timeSpace},{(int)simple}'";
                list.Add(GetArchiveTableOne(sql, colNames[i]));
            }
            bool fail = false;
            for (int i = 0; i < list.Count; i++)
            {
                //从每一个表中筛选出电导率大于1.0的Row
                string explaination = colNames[i].ToString() + ">= 1.0";
                DataRow[] rows = list[i].Select(explaination);
                if (rows.Length < 10) //如果大于1.0的行数<10,则不存在连续10秒超过1.0的情况
                {
                    if (fail)//如果上一个Table超过连续10个数据，则退出整个流程
                    {
                        break;
                    }
                    else
                    {
                        for (int j = 0; j < rows.Length; j++)//数量不到10个，则把超过的数据，改成0.1-0.5的随机数，主要是为了避免电导率空管报警的数据
                        {
                            Random ran = new Random();
                            DataRow row = rows[j];
                            row[colNames[i].ToString()] = 0.2;// NextDouble(ran, 0.10, 0.50);                        
                        }
                        list[i].AcceptChanges();
                    }
                }
                else //数据大于等于10个
                {
                    for (int j = 0; j < rows.Length - 9; j++)//判断是否是连续的10个数据
                    {
                        DataRow row1 = rows[j];   
                        DataRow row2 = rows[j + 9];
                        //判断相隔两个数据的时间间隔 0 1 2 3 4 5 6 7 8 9 
                        double span = (double)Convert.ToDateTime(row2["logtime"].ToString()).Subtract(Convert.ToDateTime(row1["logtime"].ToString())).TotalSeconds;
                        if (span == 9) //==9 表示这10个是连续数据
                        {
                            fail = true; //电导率判定失败
                            break; //跳出当前循环，进入下一个Table
                        }
                    }
                    //经过上面判断，虽然超过10个数据，但不存在连续10个超过，则判定合格，把超过的数据，改成0.1-0.5的随机数，主要是为了避免电导率空管报警的数据
                    if (!fail)
                    {
                        for (int j = 0; j < rows.Length; j++)
                        {
                            Random ran = new Random();
                            DataRow row = rows[j];
                            row[colNames[i].ToString()] = 0.2;// NextDouble(ran, 0.10, 0.50);
                        }
                        list[i].AcceptChanges();
                    }
                }
            }
            result = fail;
            return MergeDataTable(list);
        }

        public static DataTable MergeDataTable(List<DataTable> tables)
        {
            if (tables.Count <= 0)
            {
                Logs.Info("DataTable数量小于等于0");
                return null;
            }
            List<string> colNames = new List<string>
             {
                 "logtime"
             };
            List<int> rowCount = new List<int>();
            foreach (DataTable table in tables)
            {
                colNames.Add(table.Columns[1].ColumnName.ToString());
                rowCount.Add(table.Rows.Count);
            }
            if (rowCount.Max() != rowCount.Min())
            {
                Logs.Info("DataTable数据长度不一致");
                return null;
            }
            DataTable dt = CreateDataTable(colNames);
            for (int rowcount = 0; rowcount < tables[0].Rows.Count; rowcount++)  //创建一行
            {
                DataRow dr = dt.NewRow();
                dr[0] = GetLocalDT(tables[0].Rows[rowcount][0]);//归档数据的时间 转换成Local时间
                for (int tableIndex = 0; tableIndex < tables.Count; tableIndex++)//表的数量
                {
                    dr[tableIndex + 1] = tables[tableIndex].Rows[rowcount][1];//每个表当中的数据列，组成一行添加到新表中
                }
                dt.Rows.Add(dr);
            }
            return dt;
        }

        public static DataTable CreateDataTable(List<string> colNames)
        {
            if (colNames.Count <= 0)
            {
                Logs.Info("列名称数量小于等于0");
                return null;
            }
            else
            {
                DataTable dtReturn = new DataTable();
                for (int i = 0; i < colNames.Count; i++)
                {
                    if (i == 0)
                    {
                        DataColumn newColumnString = new DataColumn(colNames[i], System.Type.GetType("System.String"))
                        {
                            Caption = colNames[i],//表头
                            DefaultValue = string.Empty
                        };
                        dtReturn.Columns.Add(newColumnString);
                    }
                    else
                    {
                        DataColumn newColumnDouble = new DataColumn(colNames[i], System.Type.GetType("System.Double"))
                        {
                            Caption = colNames[i],//表头
                            DefaultValue = 0.0
                        };
                        dtReturn.Columns.Add(newColumnDouble);
                    }
                }
                return dtReturn;
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="ArchiveTagName"></param>
        /// <param name="LocalBeginDT"></param>
        /// <param name="LocalEndDT"></param>
        /// <param name="timeSpace"></param>
        /// <param name="dataType"></param>
        /// <param name="dig"></param>
        /// <param name="simple"></param>
        /// <param name="IsNewer"></param>
        /// <param name="BatchMode"></param>
        /// <param name="IsFirstTag"></param>
        /// <returns></returns>
        public static Dictionary<string, string> GetArchiveTagData(string ArchiveTagName, DateTime LocalBeginDT, DateTime LocalEndDT,
            string timeSpace = "3600", DtyTagType dataType = DtyTagType.Float, DtyDigs dig = DtyDigs.Two,
            DtySimple simple = DtySimple.First, bool IsNewer = true, bool BatchMode = false, bool IsFirstTag = false)
        {
            string winCCDateTime = GetWinCCDateTime(LocalBeginDT);
            string winCCDateTime2 = GetWinCCDateTime(LocalEndDT);
            int num = 3;
            if (IsNewer)
            {
                num = 2;
            }
            try
            {
                string sql = "TAG:R,('" + ArchiveTagName + "'),'" + winCCDateTime + "','" + winCCDateTime2 + "'," + $"'TIMESTEP={timeSpace},{(int)simple}'";
                if (BatchMode)
                {
                    sql = "TAG:R,('" + ArchiveTagName + "'),'" + winCCDateTime + "','" + winCCDateTime2 + "','TIMESTEP=0,0'";
                }
                if (dataType == DtyTagType.String)
                {
                    sql = "TAG_EX:R,('" + ArchiveTagName + "'),'" + winCCDateTime + "','" + winCCDateTime2 + "','TIMESTEP=0,0'";
                }

                OleDbDataReader oleDbDataReader = OleDbHelper.ExecuteReader(sql);
                Dictionary<string, string> dictionary = new Dictionary<string, string>();
                while (oleDbDataReader.Read())
                {
                    if (dataType == DtyTagType.Float)
                    {
                        dictionary.Add(GetLocalDT(oleDbDataReader.GetValue(1)), Math.Round(Convert.ToDouble(oleDbDataReader.GetValue(num)), (int)dig).ToString($"F{(int)dig}"));
                    }
                    else if (dataType == DtyTagType.Bool && IsFirstTag)
                    {
                        if (Convert.ToBoolean(oleDbDataReader.GetValue(num)))
                        {
                            dictionary.Add(GetLocalDT(oleDbDataReader.GetValue(1)), oleDbDataReader.GetValue(num).ToString());
                        }
                    }
                    else
                    {
                        dictionary.Add(GetLocalDT(oleDbDataReader.GetValue(1)), oleDbDataReader.GetValue(num + 1).ToString());
                    }
                }

                return dictionary;
            }
            catch (Exception ex)
            {
                Logs.Info("GetArchiveTagData:" + ex.Message);
                return null;
            }
        }

        /// <summary>
        /// Wincc归档查询的是UTC时间，转换成Local时间
        /// </summary>
        /// <param name="DT"></param>
        /// <returns></returns>
        public static string GetLocalDT(object DT)
        {
            return Convert.ToDateTime(DT).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss");
        }

        //WinCC归档使用的是UTC时间，因此需要转换一下
        /// <summary>
        /// 本地时间转换成UTC时间
        /// </summary>
        /// <param name="strtime">本地时间</param>
        /// <returns></returns>
        public static string GetWinCCDateTime(string strtime)
        {
            return System.DateTime.Parse(strtime).ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ss");
        }

        public static string GetWinCCDateTime(DateTime LocalDT)
        {
            return System.DateTime.Parse(LocalDT.ToString()).ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ss");
        }

        public static double NextDouble(Random ran, double minValue, double maxValue, int decimalPlace)
        {
            double randNum = ran.NextDouble() * (maxValue - minValue) + minValue;
            return Convert.ToDouble(randNum.ToString("f" + decimalPlace));
        }

        public static double NextDouble(Random ran, double minValue, double maxValue)
        {
            return ran.NextDouble() * (maxValue - minValue) + minValue;
        }

        ////调用：
        //Random ran = new Random();
        //double randNum = NextDouble(ran, 5.16, 8.68, 2);// 保留两位小数       
    }
}
